﻿' LibWowArmory
' by Ronald M. Clifford (roncli@roncli.com)
'
' This source code is released under the GNU Library General Public License (LGPL) Version 2.1.

Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Web
Imports System.Xml.Serialization

Namespace roncliProductions.LibWowArmory

    ''' <summary>
    ''' A class that caches the dungeons and bosses available on the Armory
    ''' </summary>
    ''' <remarks></remarks>
    Public Class Dungeons
        Inherits WowArmoryData

        Private dsConfig As New DungeonSchema.config
        Private dsData As DungeonStrings

        ''' <summary>
        ''' The URL of the dungeon and boss data
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property URL() As String
            Get
                Return "http://www.wowarmory.com/_data/dungeons.xml"
            End Get
        End Property

        ''' <summary>
        ''' Indicates to the inherited class that this request does not require login
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property RequiresLogin() As Boolean
            Get
                Return False
            End Get
        End Property

        ''' <summary>
        ''' Returns a list of available dungeons
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Dungeons() As List(Of Dungeon)
            Get
                If dsConfig Is Nothing Then
                    Return New List(Of Dungeon)
                End If
                Return (From d In dsConfig.dungeons(0).dungeon _
                        Select New Dungeon(d.hasHeroic = 1, d.id, d.key, d.levelMax, d.levelMin, GetDungeonName(d.id, d.key), d.partySize, d.raid = 1, _
                               CType(d.release, ReleaseType), _
                               (From b In d.bosses.SelectMany(Function(b) b.boss) Select New Boss(b.id, GetBossName(d.id, d.key, b.id))).ToList())).ToList()
            End Get
        End Property

        ''' <summary>
        ''' Constructor that retrieves the dungeon and boss data from either the armory or the local cache
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New()
            If Cache.Cache("LibWowArmory.Dungeons") Is Nothing Then
                MyBase.Retrieve()

                Dim xsSerializer As New XmlSerializer(dsConfig.GetType())

                Dim srXML As New StringReader(MyBase.strData)

                dsConfig = CType(xsSerializer.Deserialize(srXML), DungeonSchema.config)

                Cache.Cache.Insert("LibWowArmory.Dungeons", dsConfig, Nothing, Date.UtcNow.AddDays(1), Nothing, Caching.CacheItemPriority.NotRemovable, Nothing)
            Else
                dsConfig = CType(Cache.Cache("LibWowArmory.Dungeons"), DungeonSchema.config)
            End If

            dsData = New DungeonStrings()
        End Sub

        Private Function GetDungeonName(ByVal intDungeonID As Integer, ByVal strKey As String) As String
            Dim varDungeon = dsData.Dungeons.Where(Function(d) d.ID = intDungeonID And d.Key = strKey)
            If varDungeon.Count = 0 Then
                Return Nothing
            Else
                Return varDungeon.First().Name
            End If
        End Function

        Private Function GetBossName(ByVal intDungeonID As Integer, ByVal strKey As String, ByVal intBossID As Integer) As String
            Dim varDungeon = dsData.Dungeons.Where(Function(d) d.ID = intDungeonID And d.Key = strKey)
            If varDungeon.Count = 0 Then
                Return Nothing
            Else
                Dim dDungeon As DungeonStrings.Dungeon = varDungeon.First()
                Dim varBoss = dDungeon.Bosses.Where(Function(b) b.ID = intBossID)
                If varBoss.Count = 0 Then
                    Return Nothing
                Else
                    Return varBoss.First().Name
                End If
            End If
        End Function

        ''' <summary>
        ''' A class that encapsulates a single dungeon returned from the Armory
        ''' </summary>
        ''' <remarks></remarks>
        Public Class Dungeon

            Private blnHasHeroic As Boolean
            Private intID As Integer
            Private strKey As String
            Private intLevelMax As Integer
            Private intLevelMin As Integer
            Private strName As String
            Private intPartySize As Integer
            Private blnRaid As Boolean
            Private rRelease As ReleaseType
            Private lstBosses As List(Of Boss)

            ''' <summary>
            ''' Determines if the dungeon has an heroic version
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property HasHeroic() As Boolean
                Get
                    Return blnHasHeroic
                End Get
                Set(ByVal value As Boolean)
                    blnHasHeroic = value
                End Set
            End Property

            ''' <summary>
            ''' The dungeon's identification number
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property ID() As Integer
                Get
                    Return intID
                End Get
                Set(ByVal value As Integer)
                    intID = value
                End Set
            End Property

            ''' <summary>
            ''' The dungeon's key
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Key() As String
                Get
                    Return strKey
                End Get
                Set(ByVal value As String)
                    strKey = value
                End Set
            End Property

            ''' <summary>
            ''' The maximum suggested level for the dungeon
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property LevelMax() As Integer
                Get
                    Return intLevelMax
                End Get
                Set(ByVal value As Integer)
                    intLevelMax = value
                End Set
            End Property

            ''' <summary>
            ''' The minimum level required to enter the dungeon
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property LevelMin() As Integer
                Get
                    Return intLevelMin
                End Get
                Set(ByVal value As Integer)
                    intLevelMin = value
                End Set
            End Property

            ''' <summary>
            ''' The name of the dungeon
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Name() As String
                Get
                    Return strName
                End Get
                Set(ByVal value As String)
                    strName = value
                End Set
            End Property

            ''' <summary>
            ''' The maximum party size allowed to enter the dungeon
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property PartySize() As Integer
                Get
                    Return If(intID = 4820, 5, intPartySize) 'HACK: Reports the party size of Halls of Reflection correctly
                End Get
                Set(ByVal value As Integer)
                    intPartySize = value
                End Set
            End Property

            ''' <summary>
            ''' Determines if the dungeon is a raid
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Raid() As Boolean
                Get
                    Return blnRaid
                End Get
                Set(ByVal value As Boolean)
                    blnRaid = value
                End Set
            End Property

            ''' <summary>
            ''' The release of World of Warcraft the dungeon was introduced in
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Release() As ReleaseType
                Get
                    Return rRelease
                End Get
                Set(ByVal value As ReleaseType)
                    rRelease = value
                End Set
            End Property

            ''' <summary>
            ''' The list of bosses for this dungeon
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Bosses() As List(Of Boss)
                Get
                    Return lstBosses
                End Get
                Set(ByVal value As List(Of Boss))
                    lstBosses = value
                End Set
            End Property

            ''' <summary>
            ''' Constructor to create a new dungeon object
            ''' </summary>
            ''' <param name="blnHasHeroic"></param>
            ''' <param name="intID"></param>
            ''' <param name="strKey"></param>
            ''' <param name="strName"></param>
            ''' <param name="rRelease"></param>
            ''' <param name="lstBosses"></param>
            ''' <remarks></remarks>
            Friend Sub New(ByVal blnHasHeroic As Boolean, ByVal intID As Integer, ByVal strKey As String, ByVal intLevelMax As Integer, ByVal intLevelMin As Integer, ByVal strName As String, ByVal intPartySize As Integer, ByVal blnRaid As Boolean, ByVal rRelease As ReleaseType, ByVal lstBosses As List(Of Boss))
                Me.blnHasHeroic = blnHasHeroic
                Me.intID = intID
                Me.strKey = strKey
                Me.intLevelMax = intLevelMax
                Me.intLevelMin = intLevelMin
                Me.strName = strName
                Me.intPartySize = intPartySize
                Me.blnRaid = blnRaid
                Me.rRelease = rRelease
                Me.lstBosses = lstBosses
            End Sub

        End Class

        ''' <summary>
        ''' A class that encapsulates a single boss returned from the Armory
        ''' </summary>
        ''' <remarks></remarks>
        Public Class Boss

            Private intID As Integer
            Private strName As String

            ''' <summary>
            ''' The boss's identification number
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property ID() As Integer
                Get
                    Return intID
                End Get
                Set(ByVal value As Integer)
                    intID = value
                End Set
            End Property

            ''' <summary>
            ''' The name of the boss
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property Name() As String
                Get
                    Return strName
                End Get
                Set(ByVal value As String)
                    strName = value
                End Set
            End Property

            ''' <summary>
            ''' Constructor to create a new boss object
            ''' </summary>
            ''' <param name="intID"></param>
            ''' <param name="strName"></param>
            ''' <remarks></remarks>
            Friend Sub New(ByVal intID As Integer, ByVal strName As String)
                Me.intID = intID
                Me.strName = strName
            End Sub

        End Class

    End Class

End Namespace